﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebApp1.Controllers;
using System.IO;
using NewsMine.Utilities;
using System.Collections.Concurrent;


    public static class CacheAgainstUrlHelper
    {
        static object syncLock = new object();

        static ConcurrentDictionary<string, CachedHtmlContent> inMemoryHtmlCacheDictionary = new ConcurrentDictionary<string, CachedHtmlContent>();

        static bool? _IsInMemoryCacheEnabled = null;

        static bool IsInMemoryCacheEnabled
        {
            get
            {
                if(! _IsInMemoryCacheEnabled.HasValue)
                {
                    if (NewsMine.Configuration.ConfigurationManager.Get("IsInMemoryCacheEnabled") != null)
                        _IsInMemoryCacheEnabled = Convert.ToBoolean(NewsMine.Configuration.ConfigurationManager.Get("IsInMemoryCacheEnabled"));
                    else 
                        _IsInMemoryCacheEnabled=false;
                }

                return _IsInMemoryCacheEnabled.Value;

            }
        }

        public static string GetCacheDataFolder()
        {
            string basePath = Path.Combine(NewsMine.Configuration.ConfigurationManager.StorageBaseFolder, "Misc\\WebSiteOutputCache");

            if (Directory.Exists(basePath) == false)
            {
                Directory.CreateDirectory(basePath);
            }

            return basePath;
        }

        private static string GetHashForUrl(string url)
        {
             url = url.ToLower();
             return NewsMine.Utilities.Extensions.CreateMD5Hash(url);
        }

   
        public static void Replace(string url, CachedHtmlContent html)
        {
            if (IsInMemoryCacheEnabled == true)
            {
                inMemoryHtmlCacheDictionary.TryAdd(url.ToLower(), html);
                return;
            }

            string targetFilePath = Path.Combine(GetCacheDataFolder(), GetHashForUrl(url));
            try
            {
                lock (syncLock)
                {
                    File.WriteAllText(targetFilePath, html.Html);
                }
            }
            catch (Exception ex)
            {
                TempLogger.Log("Error while writing to cached folder... " + ex.Message, ex);
            }

            CleanUpExpiredItems();
        }

        public static CachedHtmlContent Get(string url)
        {

            if (IsInMemoryCacheEnabled == true)
            {
                CachedHtmlContent cachedItem = null;
                inMemoryHtmlCacheDictionary.TryGetValue(url.ToLower(), out cachedItem);

                return cachedItem;
                
            }

            string targetFilePath = Path.Combine(GetCacheDataFolder(), GetHashForUrl(url));

            try
            {
                if (File.Exists(targetFilePath))
                {
                    CachedHtmlContent htmlContent = new CachedHtmlContent();

                    lock (syncLock)
                    {
                        htmlContent.Html = File.ReadAllText(targetFilePath);
                    }

                    htmlContent.CreatedTime = File.GetLastWriteTime(targetFilePath);

                    return htmlContent;
                }
                else
                    return null;
            }
            catch (Exception ex)
            {
                TempLogger.Log("Error while reading cached html item..." + ex.Message, ex);

                return null;
            }
        }

        #region cleanup expired items

        static DateTime lastCleanUpTime = DateTime.MinValue;
        public static void CleanUpExpiredItems()
        {
            if (lastCleanUpTime.AddMinutes(60) < DateTime.Now)
            {
                var files = Directory.GetFiles(GetCacheDataFolder());

                DateTime fileWrittenTime = DateTime.MinValue;

                for (int i = 0; i < files.Length; i++)
                {
                    if (File.Exists(files[i]) == false)
                        continue;

                    fileWrittenTime = File.GetLastWriteTime(files[i]);
                    if (fileWrittenTime.AddHours(200) <= DateTime.Now)
                    {
                        try
                        {
                            File.Delete(files[i]);
                        }
                        catch (Exception ex)
                        {
                            TempLogger.Log("Error while deleting cached item." + ex.Message, ex);
                        }
                    }

                }

                lastCleanUpTime = DateTime.Now;
            }
        }

        #endregion
    }
